from django.shortcuts import render,redirect
#导包
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse
#导入类视图
from django.views import View

import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
#导入加密库
import hashlib
#导入图片库
#绘画库
from PIL import ImageDraw
#字体库
from PIL import ImageFont
#图片库
from PIL import Image
#随机库
import random
#文件流
import io

import requests

#导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

#导入原生sql模块
from django.db import connection

import jwt

#导入redis数据库
import redis

#导入时间模块
import time

#导入公共目录变量
from mydjango.settings import BASE_DIR

#导包
from django.db.models import Q,F

#导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

from myapp.models import User,Course,Flow

from django.utils.deprecation import MiddlewareMixin

from django.http import QueryDict


#类视图调用
from django.utils.decorators import method_decorator

#事务操作
from django.db import transaction

from redis import StrictRedis
import datetime

from myapp.myser import CourseSer,FlowSer

import time
import hmac
import base64
from hashlib import sha256
import urllib
import json


#获取关注状态
class GetFlow(APIView):
	def get(self,request):

		#获取课程id
		id=request.GET.get('id',None)
		uid=request.GET.get('uid',None)

		flow=Flow.objects.filter(uid=uid,course_id=id).first()

		if flow:
			return Response({'state':'true'})
		else:
			return Response({'state':'false'})

class AddFlow(APIView):
	def post(self,request):
		id = request.POST.get('id', None)
		uid = request.POST.get('uid', None)

		try:
			Flow.objects.create(uid=uid, course_id=id)
		except Exception as e:
			print(1)
			return Response({'state': 'false'})

		return Response({'state': 'true'})

	def get(self, request):
		id = request.GET.get('id', None)
		uid = request.GET.get('uid', None)

		try:
			Flow.objects.filter(uid=uid,course_id=id).delete()
		except Exception as e:
			return Response({'state': 'true'})
		print(2)
		return Response({'state': 'false'})

#获取购买的课程
class BuyCourse(APIView):
	def post(self,request):
		uid=request.POST.get('uid')
		flow=Flow.objects.filter(uid=uid)
		data=FlowSer(flow,many=True).data
		coursename=[]
		for i in data:
			p={}
			# 建立查询游标
			cursor = connection.cursor()
			# 执行sql
			cursor.execute('SELECT * from Course where id=%s' % i['course_id'])
			# 获取结果集
			res = dictfetchall(cursor)
			p['course_name']=res[0]['title']
			coursename.append(p)
		return Response({'data':coursename,'msg':'输出成功','code':200})

#输出构造课程分类层级关系(树)
def post_tree(data,cid):
	lists=[]
	tree={}
	list123=[]
	for item in data:
		tree[item['id']]=item

	for i in data:
		if not i['pid']:
			lists.append(tree[i['id']])
			list123.append(tree[i['id']]['name'])
		else:
			parent_id=i['pid']
			if tree[i['id']]['id']==cid:
				return list123

			if 'children' not in tree[parent_id]:
				tree[parent_id]['children']=[]
			tree[parent_id]['children'].append(tree[i['id']])


#课程详情页
class CourseDetail(APIView):
	def get(self,request):

		#获取课程id
		id=request.GET.get('id',None)

		course=Course.objects.get(pk=id)
		course_ser=CourseSer(course)


		cid=course_ser.data['cid']
		# 建立查询游标
		cursor = connection.cursor()
		# 执行sql
		cursor.execute('SELECT * from cate')
		# 获取结果集
		# res=cursor.fetchall()
		res = dictfetchall(cursor)

		cursor.execute('SELECT * from cate where id=%s'%cid)
		# 获取结果集
		# res=cursor.fetchall()
		res123 = dictfetchall(cursor)

		# 强转
		res = post_tree(res,cid)
		return Response({'data':course_ser.data,'cate_fu':res,'cate':res123[0]['name']})


#课程列表页
class CourseList(APIView):
	def get(self,request):
		#当前页
		page=request.GET.get('page',1)

		#每页展示条数
		size=request.GET.get('size',1)

		#开始位置
		data_start=(int(page)-1)*int(size)

		#结束位置
		date_end=int(page)*int(size)

		#查询
		courselist=Course.objects.all()[data_start:date_end]

		#总条数
		count=Course.objects.count()

		#序列化
		courselist_ser=CourseSer(courselist,many=True)

		return Response({'total':count,'data':courselist_ser.data})

user=0b110

permission=0b001

#装饰器
def my_decorator(func):
	def wrapper(request,*args,**kwargs):
		print('装饰器被调用')
		if user & permission:
			return func(request,*args,**kwargs)
		else:
			return HttpResponse('您没有权限')

	return wrapper

#上传头像
@my_decorator
def upload_img(request,user,permission):
	return HttpResponse('上传成功')

def dictfetchall(cursor):
	desc=cursor.description

	return [
	dict(zip([col[0] for col in desc ],row))
	for row in cursor.fetchall()
	]


#添加课程
class AddCourse(APIView):
	def post(self,request):
		title=request.POST.get('title',None)
		desc = request.POST.get('desc', None)
		price = request.POST.get('price', None)

		cid = request.POST.get('cid', None)

		file = request.FILES.get('file')

		# 写文件
		with open(os.path.join(UPLOAD_ROOT, '', file.name), 'wb') as f:
			for chunk in file.chunks():
				f.write(chunk)

		#入库
		course=Course(title=title,desc=desc,price=price,video=file.name,cid=cid)

		#保存
		course.save()

		return Response({'code':200,'message':'提交课程成功','video':file.name})

#构造课程分类层级关系(树)
def get_tree(data):
	lists=[]
	tree={}

	for item in data:
		tree[item['id']]=item

	for i in data:
		if not i['pid']:
			lists.append(tree[i['id']])
		else:
			parent_id=i['pid']
			# print(parent_id)
			if 'children' not in tree[parent_id]:
				tree[parent_id]['children']=[]
			tree[parent_id]['children'].append(tree[i['id']])

	return lists


#获取课程分类
def get_cate(request):
	#建立查询游标
	cursor=connection.cursor()
	#执行sql
	cursor.execute('SELECT * from cate')
	#获取结果集
	#res=cursor.fetchall()
	res=dictfetchall(cursor)

	#强转
	res=get_tree(res)
	return HttpResponse(json.dumps(res, indent=4, ensure_ascii=False), content_type='application/json')


#获取某个用户的权限
class GetUserAccess(View):
	def get(self,request):
		token=request.GET.get('token')
		decode_jwt = jwt.decode(token, '123', algorithms=['HS256'])
		#建立查询游标
		cursor=connection.cursor()
		#执行sql
		cursor.execute('SELECT a.username,c.node_name,C.id FROM USER a LEFT JOIN access b ON a.id = b.uid LEFT JOIN node c ON b.node_id=c.id WHERE a.id=%s;'%decode_jwt['uid'])
		#获取结果集
		# res=cursor.fetchall()
		res=dictfetchall(cursor)
		return HttpResponse(json.dumps(res,indent=4,ensure_ascii=False),content_type='application/json')


#定义验证码类
class MyCode(View):

	#内置类方法
	def get_random_color(self):

		R=random.randrange(255)
		G=random.randrange(255)
		B=random.randrange(255)

		return (R,G,B)

	def get(self,request):

		#定义画布
		img_size=(120,50)

		#定义图像对象
		image=Image.new('RGB',img_size,'white')
		#定义画笔
		draw=ImageDraw.Draw(image,'RGB')
		#定义字符串
		source='0123456789abcdefg'
		#定义容器
		code_str=''
		for i in range(4):
			#获取字符颜色
			text_color=self.get_random_color()
			#获取随机字符
			tmp_num=random.randrange(len(source))
			random_str=source[tmp_num]
			code_str+=random_str
			draw.text((10+30*i,20),random_str,text_color)

		buf=io.BytesIO()
		image.save(buf,'png')

		#保存验证码
		# request.session['code']=code_str

		sr = StrictRedis()
		sr.set('code',code_str)  # 将cpf值设置为name变量
		return HttpResponse(buf.getvalue(),'image/png')

				#打开radis客户端


#md5加密
def make_password(mypass):

    #生成对象
    md5=hashlib.md5()
    #定义加密对象
    sign_str=mypass
    #转码
    sign_utf8=str(sign_str).encode(encoding='utf-8')
    #加密
    md5.update(sign_utf8)
    #生成密文
    md5_server=md5.hexdigest()

    return md5_server

#登录接口
class Login(APIView):
	def post(self,request):
		username=request.POST.get('username',None)
		phone=request.POST.get('phone',None)
		password=request.POST.get('password',None)
		code=request.POST.get('code',None)

		# 获取验证码
		sr = StrictRedis()
		img_code=sr.get('code').decode()  # 返回值为b'cpf'

		if code != img_code:
			return Response({'code':406,'message':'图片验证错误'})

		#判断
		if username:
			user = User.objects.filter(username=username, password=make_password(password)).first()
		else:
			user = User.objects.filter(phone=phone, password=password).first()
		if user:
			encode_jwt=jwt.encode({'uid':user.id,'username':user.username},'123',algorithm='HS256')
			encode_str=str(encode_jwt,'utf-8')
			return Response({'code':200,'message':'登录成功','uid':user.id,'username':user.username,'token':encode_str})
		else:
			return Response({'code':405,'message':'您的用户名或者密码错误'})
	def put(self,request):

		password=request.POST.get('password',None)
		token=request.POST.get('token',None)
		# 解密
		decode_jwt = jwt.decode(token, '123', algorithms=['HS256'])
		User.objects.filter(username=decode_jwt['username']).update(password=make_password(password))
		return Response({'code':200,'msg':'密码修改成功'})

#用户注册
class Register(APIView):
	def post(self,requests):
		#接收参数
		username=requests.POST.get('username',None)
		password=requests.POST.get('password',None)
		phone=requests.POST.get('phone',None)

		#排重
		user=User.objects.filter(username=username).first()#.get(username=username)
		print(phone)
		if user:
			res={}
			res['code']=405
			res['message']='用户已经存在'

			return Response(res)

		#入库 捕获异常
		try:
			user=User(username=username,password=make_password(password),phone=phone)
			user.save()
			return Response({'code':200,'message':'注册成功'})
		except Exception as e:

			return Response({'code':200,'message':'用户已存在'})

#钉钉登录
def ding_url_zj(request):
    appid = 'dingoaukgkwqknzjvamdqh'
    redirect_uri = 'http://localhost:8000/dingding_back/'

    return redirect('https://oapi.dingtalk.com/connect/qrconnect?appid='+appid+'&response_type=code&scope=snsapi_login&state=STATE&redirect_uri='+redirect_uri)

#构造钉钉回调方法
def ding_back(request):

    #获取code
    code = request.GET.get("code")

    t = time.time()
    #时间戳
    timestamp = str((int(round(t * 1000))))
    appSecret ='ly-AzMKMmCKQP3geaILT_An32kEfKO3HeOtApy5CgKwjytevVZC0WYsT2gxMB160'
    #构造签名
    signature = base64.b64encode(hmac.new(appSecret.encode('utf-8'),timestamp.encode('utf-8'), digestmod=sha256).digest())
    #请求接口，换取钉钉用户名
    payload = {'tmp_auth_code':code}
    headers = {'Content-Type': 'application/json'}
    res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature='+urllib.parse.quote(signature.decode("utf-8"))+"&timestamp="+timestamp+"&accessKey=dingoaukgkwqknzjvamdqh",data=json.dumps(payload),headers=headers)

    res_dict = json.loads(res.text)
    print(res_dict)
    #判断
    user = User.objects.filter(username=res_dict['user_info']['nick']).first()

    if user:
    	return redirect('http://localhost:8000/ding_login/?uid='+str(user.id)+"&username="+user.username)
    else:
    	user = User(username=res_dict['user_info']['nick'])
    	user.save()
    	user = User.objects.filter(username=res_dict['user_info']['nick']).first()
    	return redirect('http://localhost:8000/ding_login/?uid='+str(user.id)+"&username="+user.username)

#与前端交互
class Ding_Login(APIView):
	def get(self,request):
		id=request.GET.get('uid')
		username=request.GET.get('username')
		sr=StrictRedis()					#打开radis客户端
		sr.set('uid',id)					#将cpf值设置为name变量
		sr.set('username',username)
		return redirect('http://127.0.0.1:8080/dinglogin')

	def post(self,reuqest):
		sr = StrictRedis()
		username=sr.get('username').decode()
		uid=sr.get('uid').decode()
		print(username)
		print(uid)
		encode_jwt = jwt.encode({'uid': uid, 'username': username}, '123', algorithm='HS256')
		encode_str = str(encode_jwt, 'utf-8')
		return Response({'code': 200, 'message': '登录成功','uid':uid, 'username': username, 'token': encode_str})


